#include "LongLong.h"
#include <limits>

typedef unsigned long ulong;
 __int64 LongLong2int64(long h, unsigned long l)
 {
	 bool sign = false;
	 if(h & 0x80000000)
		 sign = true;
	 h &= 0x7FFFFFFF;
	 __int64 result = 0;
	 	 
	 for(int i = 0; i < 32; i++)
	 {
		 result <<= 1;
		 if(h & 0x80000000)
			 result |=1;
		 h <<= 1;
	 }
	 for(int i = 0; i < 32; i++)
	 {
		 result = result << 1;
		 if(l & 0x80000000)
			 result |=1;
		 l <<=1;
	 }
	 if(sign)
		 result *= -1;

	 return result;
 }
 void int64toLongLong(__int64 value, long& h, unsigned long& l)
 {
	 const __int64 lowbitmask = 0x1;
	 bool sign = false;
	 if(value < 0)
	 { 
		 sign = true;
		 value *= -1;
	 }
	 h = 0;
	 l = 0;
	 for(int i = 0; i < 32; i++)
	 {
		 l |= ((value & lowbitmask) << i);
		 value >>= 1;
	 }
	 for(int i = 0; i < 32; i++)
	 {
		 
		 h |= ((value & lowbitmask) << i);
		 value >>= 1;
	 }
	 if(sign)
		h |= 0x80000000;
 }

unsigned int  LongLong::Count() 
{
	return count;
}
LongLong::LongLong(long long ll)
{
	int64toLongLong(ll, high, low);
}
LongLong::LongLong(long h, unsigned long l):high(h), low(l)
{
	count++;
};
LongLong::LongLong(const LongLong& copin_value):high(copin_value.high), low(copin_value.low)
{
	count++;
}
LongLong::~LongLong(void)
{
	count--;
};
LongLong& LongLong::operator=(const LongLong& copin_value)
{
	high = copin_value.high;
	low = copin_value.low;
	count++;
	return *this;
}
const LongLong LongLong::operator+(const LongLong& add_value) const
 {
	 __int64 first = LongLong2int64(high, low);
	 __int64 second = LongLong2int64(add_value.high, add_value.low);

	 long h;
	 ulong l;
	 int64toLongLong(first + second, h, l);
	 return LongLong(h,l); 
 }
const LongLong LongLong::operator*(const LongLong& mul_value) const
{
	 __int64 first = LongLong2int64(high, low);
	 __int64 second = LongLong2int64(mul_value.high, mul_value.low);

	 long h;
	 ulong l;
	 int64toLongLong(first * second, h, l);
	 return LongLong(h,l); 
}
const LongLong LongLong::operator/(const LongLong& div_value) const
{
	 __int64 first = LongLong2int64(high, low);
	 __int64 second = LongLong2int64(div_value.high, div_value.low);

	 long h;
	 ulong l;
	 int64toLongLong(first / second, h, l);
	 return LongLong(h,l); 
}
const LongLong LongLong::operator-(const LongLong& sub_value) const
{
	 __int64 first = LongLong2int64(high, low);
	 __int64 second = LongLong2int64(sub_value.high, sub_value.low);

	 long h;
	 ulong l;
	 int64toLongLong(first - second, h, l);
	 return LongLong(h,l); 
}
const LongLong LongLong::operator%(const LongLong& div_value) const
{
	 __int64 first = LongLong2int64(high, low);
	 __int64 second = LongLong2int64(div_value.high, div_value.low);

	 long h;
	 ulong l;
	 int64toLongLong(first - second, h, l);
	 return LongLong(h,l); 
}

const LongLong& LongLong::operator++() 
{
	__int64 value = LongLong2int64(high, low);
	int64toLongLong(value++, high, low);
	return *this; 
}
const LongLong LongLong::operator++(int) 
{
	__int64 value = LongLong2int64(high, low);
	LongLong ll(high, low);
	int64toLongLong(value++, high, low);
	return ll; 
}
const LongLong& LongLong::operator--()
{
	__int64 value = LongLong2int64(high, low);
	int64toLongLong(value--, high, low);
	return *this; 
}
const LongLong LongLong::operator--(int)
{
	__int64 value = LongLong2int64(high, low);
	LongLong ll(high, low);
	int64toLongLong(value--, high, low);
	return ll; 
}

ostream& operator<<(ostream& strm, const LongLong& ll)
 {

	return strm;

 }


unsigned int LongLong::count = 0;
 